#pragma once
#include "VideoSurfaceFwd.h"
#include "ImageFwd.h"
#include "VideoSurfaceRegion.h"
#include "ImportExport.h"

namespace ja2{ namespace sgp
{
	struct BlitFx;
 
	//! Video surface implementation.
	class VideoSurface : boost::noncopyable
	{
		// Constants
	private:
		//! Default region size.
		static std::uint_least8_t const DEFAULT_REGION_SIZE = 5;

		// Enums
	public:
		//! Blit flags.
		enum BitFlag
		{
			BF_USE_DEST_COLORKEY = 0x0001,
			BF_USE_SRC_COLORKEY = 0x0002,
			BF_FAST = 0x0004,
			BF_CLIPPED = 0x0008,
			BF_SRC_REGION = 0x0010,
			BF_COLOR_FILL = 0x0020,
			BF_SRC_SUBRECT = 0x0040,
			BF_DEST_REGION = 0x0080,
			BF_COLOR_FILL_RECT = 0x0100,
			BF_MIRROR_Y = 0x0200
		};
		//! Memory usage.
		enum MemoryUsage
		{
			MU_DEFAULT = 0x0001, /*!< Default mem usage is same as DD, try video and then try system. Will usually work.*/
			MU_VIDEO = 0x0002, /*!< Will force surface into video memory and will fail if it can't. */
			MU_SYSTEM = 0x0004 /*!< Will force surface into system memory and will fail if it can't */
		};

		// Typedefs
	private:
		//! Region list.
		typedef std::vector<VideoSurfaceRegion> RegionList_t;

		// Attributes
	private:
		//! BPP (ALWAYS 32!).
		std::uint_least8_t m_BitDepth;
		//! Handle to surface.
		VideoSurfaceHandlePtr_t m_pHandle;
		// A List of regions within the video Surface
		RegionList_t m_RegionList;
		//! Type of memory used for surface.
		MemoryUsage m_MemoryUsage;

		// Operations
	public:
		//! Get surface height.
		uint_least16_t height() const;
		//! Get surface width.
		uint_least16_t width() const;
		//! Get bith depth.
		std::uint_least8_t depth() const;
		//! Blit whole surface to destination surface at position DestX, DestY.
		/*!
			/param SrcSurface source surface that will be blitted. 
		*/
		JA2_SGP_API void blit(VideoSurface &SrcSurface, std::int_least16_t DestX, std::int_least16_t DestY, std::uint_least32_t Flags, BlitFx *pBltFx);
		//! Get region.
		VideoSurfaceRegion get_region(std::uint_least16_t RegionId) const;
		//! Get surface dimensions as rect.
		Rect get_rect() const;
		//! Get memory usage.
		MemoryUsage get_memory_usage() const;
		//! Flip surface.
		void flip();
	private:
		//! Set video surface from image.
		void set_surface_from_image(ImagePtr_t const &pImage, std::uint_least16_t X, std::uint_least16_t Y, Rect const &Rect_);
		//! See set_surface_from_image.
		void set_surface_from_image(ImagePtr_t const &pImage, std::uint_least16_t X, std::uint_least16_t Y);
		//! Blit surface using DD.
		void blit_using_dd(VideoSurface &SrcVSurface, std::uint_least16_t DestX, std::uint_least16_t DestY, Rect const &SrcRect, std::uint_least32_t Flags);
		//! Clipt rectangles.
		static bool clip_releated_src_dest_rectangles(VideoSurface &Dest, VideoSurface &Src, Rect &DestRect, Rect &SrcRect);

		// Construction/Destruction
	public:
		//! Create empty surface
		VideoSurface(std::uint_least8_t Depth = 0, VideoSurfaceHandlePtr_t const &pHandle = VideoSurfaceHandlePtr_t(), MemoryUsage MemoryUsage_ = MU_DEFAULT);
	};

	inline std::uint_least8_t VideoSurface::depth() const
	{
		return m_BitDepth;
	}
} /*sgp*/} /*ja2*/
